package org.report4service.services;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import javax.microedition.rms.RecordComparator;
import javax.microedition.rms.RecordEnumeration;
import javax.microedition.rms.RecordStoreNotOpenException;

import org.report4service.dbutils.RMSStorage;
import org.report4service.model.User;
import org.report4service.utils.UserParser;

/**
 * implements {@link UserService}
 * 
 * @author Jmpango
 * 
 */
public class UserServiceImpl extends RMSStorage {

    private UserParser userParser = new UserParser();
    private static String dBName = "userDB";

    /** Default constructor */
    public UserServiceImpl() {
        rc = new SubComparator();
        setdBName(dBName);
        startDB();

    }

    public void startDB() {
        try {
            openDB(getdBName());
            if (getNumRecords() == 0) {
                addDbRecord(userParser.getUserRecord(new User("admin", "1234")));
            }

        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public void shutDB(){
        try {
            closeDB();
        } catch (Exception ex) {
            ex.printStackTrace();
        } 
    }

    public User getUser() {
        try {
            User user = new User();
            user = getRecord(user);
            return user;
        } catch (RecordStoreNotOpenException ex) {
            ex.printStackTrace();
        }
        return null;
    }

    /**
     * gets user from the enumerated records
     * 
     * @param user
     * @return
     * @throws RecordStoreNotOpenException
     */
    private User getRecord(User user) throws RecordStoreNotOpenException {
        int index = 0;
        RecordEnumeration recordEnumeration = enumerateRecords();
        while (recordEnumeration.hasNextElement()) {
            try {
                user = deserialise(recordEnumeration.nextRecord(), ++index, getNumRecords());
                return user;
            } catch (Exception e) {
                eventListener.errorOccured("errors:", e);
            }
        }

        return null;
    }

    /**
     * Udates the old user record with new record.
     * 
     * @param newUser
     * @return
     */
    public boolean changeUserPassword(String newPassword) {
        User user = getUser();

        if (user != null) {
            String oldUserRecord = userParser.getUserRecord(user);
            user.setPassword(newPassword);
            String newUserRecord = userParser.getUserRecord(user);

            try {
                if (updateDbRecord(oldUserRecord, newUserRecord)) {
                    return true;
                } else {
                    return false;
                }
            } catch (Exception e) {
                eventListener.errorOccured("errors:", e);
            }
        } else {
            return false;
        }

        return false;
    }

    public User deserialise(byte[] data, int recordId, int maxRecords) throws IOException {
        ByteArrayInputStream bais = new ByteArrayInputStream(data);
        DataInputStream dis = new DataInputStream(bais);

        User user = userParser.getUser(dis.readUTF(), recordId, maxRecords);

        bais.reset();
        dis.close();
        bais.close();

        return user;
    }

    /** Compare two records */
    private class SubComparator implements RecordComparator {

        public int compare(byte[] rec1, byte[] rec2) {
            try {
                String oldUserRecord = new String(rec1);
                String newUserRecord = new String(rec2);

                int result = oldUserRecord.compareTo(newUserRecord);

                if (result == 0) {
                    return RecordComparator.EQUIVALENT;
                } else if (result < 0) {
                    return RecordComparator.PRECEDES;
                } else {
                    return RecordComparator.FOLLOWS;
                }
            } catch (Exception e) {
                return RecordComparator.EQUIVALENT;
            }
        }
    }

    public boolean save(User user) {
        return false;
    }

    /**
     * @return the userParser
     */
    public UserParser getUserParser() {
        return userParser;
    }

    /**
     * @param userParser
     *            the userParser to set
     */
    public void setUserParser(UserParser userParser) {
        this.userParser = userParser;
    }

    public static String getdBName() {
        return dBName;
    }

    public static void setdBName(String dBName) {
        UserServiceImpl.dBName = dBName;
    }
}
